Skip to content

Enable repository delegation in unified MCP gateway mode - #12753

Merged
lpcox merged 5 commits into
mainfrom
copilot/enable-repository-delegation
Sep 8, 2026
Merged

Enable repository delegation in unified MCP gateway mode#12753
lpcox merged 5 commits into
mainfrom
copilot/enable-repository-delegation

Conversation

Copilot AI commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

github-repository-delegation-v1 only initialized in proxy mode, leaving gh-aw’s unified gateway without the private control listener even when all delegation activation inputs were present. AWF could receive a control endpoint, but reconciliation failed because no controller was serving it.

  • Unified delegation activation

    • Resolve the existing five delegation environment inputs during normal gateway startup.
    • Fail startup on partial or malformed activation instead of silently running without delegation.
    • Attach the resolved delegation store to the unified server config.
  • Private control plane

    • Start the delegation control listener alongside the unified MCP gateway.
    • Expose the existing status, reconcile, create-or-confirm, revoke, and revoke-by-labels operations through the private control endpoint.
    • Shut down the control listener with the gateway and persist delegation state.
  • Delegated /mcp/github data plane

    • Admit live delegated executor bearers through gateway auth without treating them as control credentials.
    • Authorize delegated tool calls against the shared store before backend execution.
    • Restrict delegated bearers to the exact bound owner/repo and closed github-repository-read-v1 tool set.
ctx, err := us.authorizeDelegatedToolCall(ctx, serverID, toolName, args)
if err != nil {
    return mcp.NewErrorCallToolResult(err)
}

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for repository delegation in unified MCP gateway mode Enable repository delegation in unified MCP gateway mode Sep 8, 2026
Copilot AI requested a review from lpcox September 8, 2026 15:56
@lpcox
lpcox marked this pull request as ready for review September 8, 2026 15:59
Copilot AI balanced review requested due to automatic review settings September 8, 2026 15:59
@lpcox

lpcox commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Delegated calls can bypass revocation without gateway keys and fail under per-agent policies, while required integration coverage is absent.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Enables repository delegation in unified MCP gateway mode by sharing delegation state across control and data planes.

Changes:

  • Initializes delegation during unified startup and serves the private control API.
  • Authenticates and authorizes delegated GitHub tool calls.
  • Adds shared delegation configuration and unit coverage.
File summaries
File Description
internal/server/unified.go Attaches delegation runtime state.
internal/server/middleware.go Adds delegated authentication.
internal/server/middleware_auth.go Accepts live executor bearers.
internal/server/delegation.go Implements control and authorization logic.
internal/server/delegation_test.go Tests delegated calls and authentication.
internal/server/backend_call.go Authorizes calls before execution.
internal/proxy/delegation.go Reuses shared delegation configuration.
internal/delegation/store.go Detects live executor bearers.
internal/delegation/store_test.go Tests bearer revocation handling.
internal/delegation/config.go Defines shared runtime configuration.
internal/config/config_core.go Adds delegation to gateway configuration.
internal/cmd/root.go Starts and stops unified delegation services.
internal/cmd/proxy.go Returns shared runtime configuration.
internal/cmd/delegation.go Manages the unified control listener.
internal/cmd/delegation_test.go Tests control-listener status.
Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 3
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +108 to +111
func applyAuthIfConfiguredWithDelegation(apiKeys []string, delegatedAuthenticator func(string) bool, handler http.HandlerFunc) http.HandlerFunc {
if len(apiKeys) > 0 {
logAuth.Print("Auth key configured, applying middleware")
return authMiddleware(apiKeys, handler)
return authMiddlewareWithDelegation(apiKeys, delegatedAuthenticator, handler)
}()

sessionID := us.getSessionID(ctx)
ctx, err := us.authorizeDelegatedToolCall(ctx, serverID, toolName, args)
"github.com/stretchr/testify/require"
)

func TestStartUnifiedDelegationControlServesStatus(t *testing.T) {
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

@lpcox lpcox left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes because the unified controller now starts, but the delegated data plane is still unusable under the exact gh-aw configuration and admits capabilities outside the closed delegation policy.

Before merge, add a real root-command integration test that launches the config-stdin unified mode with all five delegation environment inputs, the private listener, and AgentPolicies exactly as gh-aw emits them. Exercise status, reconcile, create-or-confirm, revoke, and revoke-by-labels over the control port; use the minted bearer through /mcp/github for an allowed call; prove denial for other repositories, tools, and non-tool MCP capabilities; then verify revocation and restart/recovery behavior.

The prior CI runs reported three testifylint failures. Head d7955c7 is specifically intended to fix those diagnostics, so the refreshed head still needs a green lint rerun.

Comment thread internal/server/delegation.go Outdated
Comment thread internal/server/middleware.go Outdated
@lpcox

lpcox commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

@copilot address all review feedback

Copilot AI commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix the linting errors https://github.com/github/gh-aw-mcpg/actions/runs/34247413409/job/102135837990?pr=12753

Fixed in d7955c7. The referenced testifylint errors are resolved, and validation passed with go test ./internal/cmd ./internal/server, golangci-lint v2.13.2, and make agent-finished.

Copilot AI requested a review from lpcox September 8, 2026 16:13

Copilot AI commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix the linting errors https://github.com/github/gh-aw-mcpg/actions/runs/34247413409/job/102135837990?pr=12753

Verified at d7955c7: the referenced testifylint diagnostics are cleared locally with golangci-lint run --timeout=5m using v2.13.2 (0 issues).

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

Copilot AI commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address all review feedback

Addressed in c58599e. The current branch carries the delegated authorization through the static AgentPolicies check only after store authorization, exposes delegated sessions through a filtered github-repository-read-v1 tool surface, rejects non-tool delegated MCP methods, and adds root-command integration coverage for control operations, allowed/denied calls, expiry, revocation replay, restart persistence, and partial activation failure. Validation passed with targeted delegation tests, golangci-lint run --timeout=5m, and make agent-finished.

@lpcox

lpcox commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

@copilot address the review feedback #12753 (comment)

…nd listener-conflict coverage

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

Copilot AI commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address the review feedback #12753 (comment)

Addressed — see the reply on the linked discussion thread and the latest commit for the fix and added test coverage.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

🔒 mcpg Read-Only Stress — gvisor

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: gvisor

Part Surface Op Result Expected Status
A MCP reads data (list_issues, list_pull_requests, get_file_contents, list_commits) ALLOWED
B MCP writes (issue_write etc.) all 7 targets absent from the 23-tool read-only catalog (e.g. issue_write -> "unknown tool") BLOCKED ⚠️
C CLI reads (proxied github CLI on PATH) data returned for all reads ALLOWED
D CLI REST writes gh unauthenticated in this sandbox (gh auth status: not logged in; gh api requires GH_TOKEN) — no write attempted BLOCKED ⚠️
E CLI GraphQL mutations same auth gap as D — not attempted BLOCKED ⚠️

Overall: INCONCLUSIVE

No write leaked. Part B could not distinguish gateway-level enforcement from backend GITHUB_READ_ONLY=1 config since all write-tool targets were absent from the exposed tool catalog entirely (gh-aw's tools.github: always forces read-only backend). Parts D/E could not be exercised because gh CLI has no credentials in this environment. Read-only holds identically to the default runtime, but full gateway-level write-blocking evidence for gvisor requires follow-up work (dedicated MCP-tool probe outside tools.github: wrapper, and an authenticated gh token for REST/GraphQL write tests).

🔒 mcpg read-only stress (gVisor runtime) by Read-Only Stress: gVisor runtime

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

🔒 mcpg Read-Only Stress — default

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: default (normal container isolation)

Part Surface Op Result Expected Status
A MCP reads (list_issues, list_pull_requests, get_file_contents, list_commits) data returned ALLOWED
B MCP writes (add_issue_comment/star_repository/issue_write/create_branch/create_or_update_file/create_pull_request) all 6 write tools absent from catalog BLOCKED ⚠️
C CLI reads (proxied github CLI) data returned ALLOWED
D CLI REST writes (reaction/star/issue/comment) gh unauthenticated, not attempted BLOCKED ⚠️
E CLI GraphQL mutations (addReaction/addStar/createIssue) gh unauthenticated, not attempted BLOCKED ⚠️

Overall: INCONCLUSIVE

Notes:

  • Only 23 read-only tools are exposed by the gateway-backed github MCP/CLI proxy (get_, list_, search_*, issue_read, pull_request_read); none of the 6 targeted write tools exist in the catalog, so no write attempt ever reached a write-capable backend to independently test mcpg's own DIFC/guard layer (per gh-aw's GITHUB_READ_ONLY=1 design). This confirms backend/toolset configuration but not the gateway's own blocking layer.
  • gh CLI had no GH_TOKEN set in this environment (You are not logged into any GitHub hosts), so Parts D and E could not be exercised at all — no writes attempted, no leak.
  • No reactions, stars, issues, comments, branches, files, or PRs were created during this run.

🔒 mcpg read-only stress (default AWF runtime) by Read-Only Stress: default runtime

@lpcox lpcox left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified on head bd2fe68. The dynamic-policy bypass is limited to calls already authorized by the delegation store, non-tool and malformed/batched JSON-RPC requests fail closed, and the root-command integration coverage now exercises the control/data-plane boundary, credential separation, listener failure, revocation, and restart persistence. Full local completion and integration suites pass.

@lpcox
lpcox merged commit 6940ffe into main Sep 8, 2026
37 of 38 checks passed
@lpcox
lpcox deleted the copilot/enable-repository-delegation branch September 8, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable repository delegation in unified MCP gateway mode

3 participants